import { _decorator, Node, Vec3, v3, Tween, Animation, tween } from 'cc';
import { GlobalConfig } from '../../../Init/Config/GlobalConfig';
import { GlobalEnum } from '../../../Init/Config/GlobalEnum';
import EventManager from '../../../Init/Managers/EventManager';
import { EventTypes } from '../../../Init/Managers/EventTypes';
const { ccclass, property } = _decorator;

@ccclass('TankAnim')
export class TankAnim {
    node: Node = null;
    _rot = v3();
    _anim: Animation = null;
    _tower: Node = null;
    // #region ------------生命周期--------
    constructor(node: Node, tower: Node) {
        this.node = node;
        this._tower = tower;
        this._anim = node.getComponent(Animation);
    }

    reset() {
        this.resetState();
    }

    setData(rot: Vec3) {
        this._rot = rot;
        this.setStateData();
    }

    updateAnim(dt) {
        this.updateState(dt);
    }

    //#endregion

    // #region -----------私有------------

    tmpR = v3();
    rotate() {
        this.tmpR.set(this.node.eulerAngles);
        this.tmpR.y = this._rot.y;
        this._tower.eulerAngles = this.tmpR;
    }
    // #endregion

    //#region -------------行为状态控制-------
    private _stateRecs: { [state: number]: TankAtkSate } = {};
    public _curState: GlobalEnum.TankClips = null;

    /**设置初始状态 */
    private setStateData() {
        this._stateRecs[GlobalEnum.TankClips.Idle] = new TankIdleSate(this);
        this._stateRecs[GlobalEnum.TankClips.Atk] = new TankAtkSate(this);
        this._stateRecs[GlobalEnum.TankClips.Death] = new TankDeathSate(this);

        setTimeout(() => {
            this.changeState(GlobalEnum.TankClips.Idle);
        }, 0);
    }
    /**重置状态 */
    private resetState() {
        for (const key in this._stateRecs) {
            this._stateRecs[key].offEvents();
        }
        this._stateRecs = {};
        this._curState = null;
    }
    /**
    * 切换状态
    * @param state 
    * @param enterData 传入参数
    * @param isForth 是否强制切换
    * @returns 
    */
    public changeState(state: GlobalEnum.TankClips, enterData?, isForth = false) {
        if (this._curState === state && !isForth) return;
        // clog.log('role:', TankClips[state]);
        //退出之前的状态
        if (this._stateRecs[this._curState]) {
            this._stateRecs[this._curState].exit();
        }
        //切换到新的状态
        if (this._stateRecs[state]) {
            this._curState = state;
            this._stateRecs[this._curState].enter(enterData);
        }
    }
    /**更新状态 */
    private updateState(dt) {
        if (this._stateRecs[this._curState]) {
            this._stateRecs[this._curState].update(dt);
        }
    }

    // #endregion
}

export class TankState {
    cmp: TankAnim = null;
    constructor(cmp: TankAnim) {
        this.cmp = cmp;
    }

    onEvents() { }
    offEvents() { }

    enter(d?) {

    }
    update(dt) {

    }
    exit() {

    }
}
//待机
export class TankIdleSate extends TankState {
    shakePos = v3();
    enter(d?: any): void {
        this.cmp._anim.play('idle');
    }
    update(dt: any): void {

    }
    exit(): void {
        Tween.stopAllByTarget(this.shakePos);
    }
}
//攻击
export class TankAtkSate extends TankState {
    shakePos = v3();
    enter(d?: any): void {
    }
    update(dt: any): void {
        this.cmp.rotate();
    }

    exit(): void {
        Tween.stopAllByTarget(this.shakePos);
    }
}
//死亡
export class TankDeathSate extends TankState {
    _tmpP = v3();
    _curt = 0;
    _delay = 1;
    _isFinish = false;

    enter(d?: any): void {
        //爆炸效果
        for (let i = 0; i < 6; i++) {
            setTimeout(() => {
                if (!this.cmp.node) return;
                this._tmpP.x = this.cmp.node.parent.position.x + Math.random() * 4 - 2;
                this._tmpP.z = this.cmp.node.parent.position.z + Math.random() * 4 - 2;
                this._tmpP.y = 1 + Math.random();
                let p = v3(this._tmpP);
                EventManager.emit(EventTypes.EffectEvents.show2DEffect, { t: GlobalEnum.Effect2DType.TankBoom, p: p });
            }, 200 * i);
        }

        this._curt = 0;
        this._isFinish = false;
    }

    update(dt: any): void {
        if (!this._isFinish) {
            this._curt += dt;
            if (this._curt >= this._delay) {
                this._isFinish = true;
                this.cmp._anim.play('death');
            }
        }
    }
}